package com.xiyuan.smartutils.template.engine.statement;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.template.engine.StatementParser;
import com.xiyuan.smartutils.template.engine.TagType;
import com.xiyuan.smartutils.template.engine.VariableMap;
import com.xiyuan.smartutils.template.engine.exception.StatementException;

import java.io.PrintWriter;

/**
 * 退出循环, 格式为：<#break/>
 *
 * @author lgz 2020年10月29日 新建与整理
 * @see _RETURN 退出函数或执行结束
 * @see _Continue 继续下一循环
 */
public final class _Break extends Statement {
    private static final long serialVersionUID = 1L;
    
    /**
     * 用于跳出循环
     */
    public static final class BreakException extends RuntimeException {
        private static final long serialVersionUID = 1L;
        private final String forSymbol;
        
        public BreakException(String forSymbol) {
            this.forSymbol = forSymbol;
        }
        
        public String getForSymbol() {
            return forSymbol;
        }
    }
    
    private String forSymbol;// 指定退出哪一层循环的标志
    
    public _Break(StatementParser parser) {
        super(parser);
    }
    
    @Override
    public TagType getType() {
        return TagType.BREAK;
    }
    
    protected void build(VariableMap variableMap, PrintWriter out) {
        throw new BreakException(forSymbol);// 跳出循环
    }
    
    @Override
    public boolean parseTag(StatementParser parser) throws StatementException {
        StringBuilder value = new StringBuilder();
        int expressionLine = this.getLineNo(), column = 0;
        char ch = 0;
        boolean space = false;
        while (parser.hasNext()) {
            ch = parser.next();
            if (value.length() == 0 && Validates.isWhitespace(ch)) {
                space = true;
                continue;
            }
            
            value.append(ch);
            if (value.length() == 1) {
                expressionLine = parser.getLineNum();
                column = parser.getColumn();
            }
            
            // 判断标签是否结束 ,当前标签为‘>’视为结束
            int endTagIndex = ch == _GATHER_ ? value.length() - 1 : -1;
            if (endTagIndex > 0 && value.charAt(endTagIndex - 1) == _SLASH_) {
                endTagIndex--;// 如果是 ‘/>’ 结束则需要重置 结束索引 为‘/’对应的索引
            }
            else {
                // 未结束
                endTagIndex = -1;
            }
            if (endTagIndex != -1) {
                // 标签结束
                
                if (endTagIndex != 0) {forSymbol = StrUtils.trim(value.substring(0, endTagIndex));}
                
                // 不是break标签，只是以<#break 开头而已
                if (forSymbol != null && !space) return false;
                
                if (forSymbol != null && !Validates.isJavaNameIdentifier(forSymbol)) {
                    String msg = TagType.BREAK + "标签无效for循环点“" + forSymbol + "”，请参见Java命名规范。";
                    throw new StatementException(this.getPath(), expressionLine, column, msg);
                }
                
                this.setCompleteTag();
                break;
            }
        }
        
        if (!this.isCompleteTag()) {
            throw new StatementException(this.getPath(),
                                         this.getLineNo(),
                                         this.getBeginColumn(),
                                         "文档已结束。" + TagType.BREAK + "标签未找到结束符‘/>’");
        }
        this.setStatement(this.getStatement() + (forSymbol != null
                                                 ? " " + forSymbol
                                                 : "") + getType().getTagComplete());
        return true;
    }
    
    /**
     * 获取循环层标志
     */
    public String getForSymbol() {
        return forSymbol;
    }
    
}
